#include "common.h"
#include <execinfo.h>
// 内存块跟踪结构
typedef struct memory_block {
    void* ptr;
    size_t size;
    const char* file;
    int line;
    struct memory_block* next;
} memory_block_t;

static memory_block_t* memory_list = NULL;
static pthread_mutex_t memory_mutex = PTHREAD_MUTEX_INITIALIZER;
static atomic_uint_fast64_t total_allocated = 0;
static atomic_uint_fast64_t current_allocated = 0;

void* _ltgsql_malloc(size_t size, const char* file, int line) {
    void* ptr = malloc(size);
    if (!ptr) {
        ltgsql_log(LTGSQL_LOG_ERROR, "Memory allocation failed: %zu bytes", size);
        return NULL;
    }

    pthread_mutex_lock(&memory_mutex);

    memory_block_t* block = malloc(sizeof(memory_block_t));
    if (!block) {
        free(ptr);
        pthread_mutex_unlock(&memory_mutex);
        return NULL;
    }

    block->ptr = ptr;
    block->size = size;
    block->file = file;
    block->line = line;
    block->next = memory_list;
    memory_list = block;

    total_allocated += size;
    current_allocated += size;

    pthread_mutex_unlock(&memory_mutex);

    return ptr;
}

void* _ltgsql_calloc(size_t count, size_t size, const char* file, int line) {
    size_t total_size = count * size;
    void* ptr = calloc(count, size);
    if (!ptr) {
        ltgsql_log(LTGSQL_LOG_ERROR, "Memory allocation failed: %zu * %zu bytes", count, size);
        return NULL;
    }

    pthread_mutex_lock(&memory_mutex);

    memory_block_t* block = malloc(sizeof(memory_block_t));
    if (!block) {
        free(ptr);
        pthread_mutex_unlock(&memory_mutex);
        return NULL;
    }

    block->ptr = ptr;
    block->size = total_size;
    block->file = file;
    block->line = line;
    block->next = memory_list;
    memory_list = block;

    total_allocated += total_size;
    current_allocated += total_size;

    pthread_mutex_unlock(&memory_mutex);

    return ptr;
}

void _ltgsql_free(void* ptr, const char* file, int line) {
    if (!ptr) return;

    pthread_mutex_lock(&memory_mutex);

    memory_block_t** current = &memory_list;
    while (*current) {
        if ((*current)->ptr == ptr) {
            memory_block_t* to_free = *current;
            *current = to_free->next;

            current_allocated -= to_free->size;
            free(to_free);
            free(ptr);

            pthread_mutex_unlock(&memory_mutex);
            return;
        }
        current = &(*current)->next;
    }

    pthread_mutex_unlock(&memory_mutex);
    ltgsql_log(LTGSQL_LOG_WARNING, "Attempt to free unknown pointer: %p at %s:%d", ptr, file, line);
}

char* _ltgsql_strdup(const char* str, const char* file, int line) {
    if (!str) return NULL;

    size_t len = strlen(str) + 1;
    char* new_str = _ltgsql_malloc(len, file, line);
    if (new_str) {
        memcpy(new_str, str, len);
    }
    return new_str;
}

// 内存统计函数
void ltgsql_memory_stats() {
    pthread_mutex_lock(&memory_mutex);

    ltgsql_log(LTGSQL_LOG_INFO, "Memory Statistics:");
    ltgsql_log(LTGSQL_LOG_INFO, "  Total allocated: %lu bytes", total_allocated);
    ltgsql_log(LTGSQL_LOG_INFO, "  Current allocated: %lu bytes", current_allocated);

    size_t block_count = 0;
    memory_block_t* current = memory_list;
    while (current) {
        block_count++;
        current = current->next;
    }

    ltgsql_log(LTGSQL_LOG_INFO, "  Active memory blocks: %zu", block_count);

    pthread_mutex_unlock(&memory_mutex);
}